#include "Defs.h"
#include "String.h"


String_T::String_T()
	:_sz(0)
	,_len(0)
	,_isSymlink(true)
{}

String_T::String_T(const char * sz)
	:_sz((char *)sz)
	,_len(lstrlen(sz))
	,_isSymlink(true)
{}

String_T::String_T(const char * sz, unsigned int len)
	:_sz((char *)sz)
	,_len(len)
	,_isSymlink(true)
{}

String_T::String_T(const String_T & str)
{
	if( &str != this )
	{
		if( str._isSymlink )
		{
			_sz = str._sz;
			_len = str._len;
			_isSymlink = true;
		}
		
		else
		{
			_sz = 0;
			_len = str._len;
			_isSymlink = false;

			if( str._len )
			{
				_sz = (char *)Memory_T::Alloc((str._len + 1) * sizeof(char));
				RtlMoveMemory(_sz, str._sz, str._len);
			}
		}
	}
}

String_T & String_T::operator=(const String_T & str)
{
	if( &str != this )
	{
		Free();
		
		if( str._isSymlink )
		{
			_sz = str._sz;
			_len = str._len;
			_isSymlink = true;
		}
		
		else
		{
			_sz = 0;
			_len = str._len;
			_isSymlink = false;

			if( str._len )
			{
				_sz = (char *)Memory_T::Alloc((str._len + 1) * sizeof(char));
				RtlMoveMemory(_sz, str._sz, str._len);
			}
		}
	}

	return *this;
}

String_T::~String_T()
{
	Free();
}

void String_T::Free()
{
	if( !_isSymlink && _sz )
	{
		FREE(_sz);
	}

	_sz = 0;
	_len = 0;
	_isSymlink = true;
}

bool String_T::Equals(const String_T & str, bool isCaseSensitive) const
{
	if( !str._sz || (str._len != _len) )
	{
		return false;
	}

	return 
		(isCaseSensitive && !memcmp(_sz, str._sz, str._len)) || 
		(!isCaseSensitive && !_memicmp(_sz, str._sz, str._len));
}

bool String_T::StartsWith(const String_T & str, bool isCaseSensitive) const
{
	if( !str._sz )
	{
		return false;
	}

	if( (str._len == 0) || (str._len > _len) )
	{
		return false;
	}

	if( isCaseSensitive )
	{
		return !memcmp(_sz, str._sz, str._len);
	}

	return !_memicmp(_sz, str._sz, str._len);
}

unsigned int String_T::LastIndexOf(const String_T & str) const
{
	if( !_sz || !str._sz )
	{
		return _len;
	}

	if( !str._len || (str._len > _len) )
	{
		return _len;
	}

	for( unsigned int iSeek = (_len - str._len) ; iSeek > 0 ; iSeek-- )
	{
		if( !memcmp(_sz + iSeek, str._sz, str._len) )
		{
			return iSeek;
		}
	}

	if( !memcmp(_sz, str._sz, str._len) )
	{
		return 0;
	}

	return _len;
}

void String_T::Concat(const String_T & str)
{
	if( !str._sz || (str._len == 0) )
	{
		return;
	}

	unsigned int len = _len + str._len;

	void * pv = Memory_T::Alloc((len + 1) * sizeof(char));
	
	if( _len )
	{
		RtlMoveMemory((unsigned char *)pv, _sz, _len);
	}

	RtlMoveMemory((unsigned char *)pv + _len, str._sz, str._len);

	Free();

	_sz = (char *)pv;
	_sz[len] = '\0';
	_len = len;
	_isSymlink = false;
}

void String_T::Create(unsigned int len)
{
	Free();

	_sz = (char *)Memory_T::Alloc((len + 1) * sizeof(char));
	_len = len;
	_isSymlink = false;
}
